package com.hospital.register.common.helper;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.hospital.register.common.exception.BusinessException;
import com.hospital.register.common.result.Result;
import com.hospital.register.common.result.ResultCodeEnum;
import com.hospital.register.common.utils.HttpUtil;
import com.hospital.register.common.utils.MD5;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

@Slf4j
public class HttpRequestHelper {

    public static void main(String[] args) {
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("d", "4");
        paramMap.put("b", "2");
        paramMap.put("c", "3");
        paramMap.put("a", "1");
        paramMap.put("timestamp", getTimestamp());
        log.info(getSign(paramMap, "111111111"));
    }

    /**
     * @param paramMap
     * @return
     */
    public static Map<String, Object> switchMap(Map<String, String[]> paramMap) {
        Map<String, Object> resultMap = new HashMap<>();
        for (Map.Entry<String, String[]> param : paramMap.entrySet()) {
            resultMap.put(param.getKey(), param.getValue()[0]);
        }
        return resultMap;
    }

    /**
     * 请求数据获取签名
     *
     * @param paramMap
     * @param signKey
     * @return
     */
    public static String getSign(Map<String, Object> paramMap, String signKey) {
        if (paramMap.containsKey("sign")) {
            paramMap.remove("sign");
        }

        TreeMap<String, Object> sortedParamMap = null;
        if (paramMap instanceof TreeMap) {
            sortedParamMap = (TreeMap<String, Object>) paramMap;
        } else {
            sortedParamMap = new TreeMap<>(paramMap);
        }

        StringBuilder allParam = new StringBuilder();
        for (Map.Entry<String, Object> param : sortedParamMap.entrySet()) {
            allParam.append(param.getValue()).append("|");
        }
        allParam.append(signKey);
        log.info("加密前：" + allParam.toString());
        String md5 = MD5.encrypt(allParam.toString());
        log.info("加密后：" + md5);
        return md5;
    }

    /**
     * 签名校验
     *
     * @param paramMap
     * @param signKey
     * @return
     */
    public static boolean isSignEquals(Map<String, Object> paramMap, String signKey) {
        String sign = (String) paramMap.get("sign");
        String md5Str = getSign(paramMap, signKey);
        if (!sign.equals(md5Str)) {
            return false;
        }
        return true;
    }

    /**
     * 获取时间戳
     *
     * @return
     */
    public static long getTimestamp() {
        return System.currentTimeMillis();
    }

    /**
     * 封装同步请求
     *
     * @param paramMap
     * @param url
     * @return
     */
    public static JSONObject sendRequest(Map<String, Object> paramMap, String url) {
        String result = "";
        try {
            //封装post参数
            StringBuilder postdata = new StringBuilder();
            for (Map.Entry<String, Object> param : paramMap.entrySet()) {
                postdata.append(param.getKey()).append("=")
                        .append(param.getValue()).append("&");
            }
            log.info(String.format("--> 发送请求：post data %1s", postdata));
            byte[] reqData = postdata.toString().getBytes("utf-8");
            byte[] respdata = HttpUtil.doPost(url, reqData);
            result = new String(respdata);
            log.info(String.format("--> 应答结果：result data %1s", result));
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return JSONObject.parseObject(result);
    }

    /**
     * 向院方发起请求
     * 会主动生成时间戳
     * 主动对参数加密
     *
     * @param param   参数
     * @param url     地址
     * @param signKey 院方的签名秘钥
     * @return 响应结果
     */
    public static <ResultData> Result<ResultData> sendToHospital(Object param, String url, String signKey, Class<ResultData> resultDataType) {
        try {
            //转换成 TreeMap
            TreeMap paramMap = null;
            if (param instanceof TreeMap) {
                paramMap = (TreeMap<String, Object>) param;
            } else {//参数不是 TreeMap 类型
                // 创建 ObjectMapper 实例
                ObjectMapper objectMapper = new ObjectMapper();
                // 将对象转换为 JSON 字符串
                String jsonString = objectMapper.writeValueAsString(param);
                // 将 JSON 字符串转换为 TreeMap
                paramMap = objectMapper.readValue(jsonString, TypeFactory.defaultInstance().constructMapType(TreeMap.class, String.class, Object.class));
            }

            //生成请求签名
            paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
            String requestSign = getSign(paramMap, signKey);
            paramMap.put("sign", requestSign);

            //发送请求
            JSONObject jsonObject = sendRequest(paramMap, url);
            if (jsonObject == null || jsonObject.isEmpty()) {
                throw new BusinessException("院方响应数据为空", ResultCodeEnum.SERVICE_ERROR.getCode());
            }

            Integer responseCode = jsonObject.getInteger("code");
            String responseMessage = jsonObject.getString("message");
            ResultData data =null;
            if (jsonObject.getJSONObject("data")!=null){
                 data = jsonObject.getJSONObject("data").toJavaObject(resultDataType);
            }
            return Result.ok(data)
                    .code(responseCode)
                    .message(responseMessage);
        } catch (JsonProcessingException e) {
            log.error("调用医院接口失败，Json 结果转换错误", e);
            throw new BusinessException("调用医院接口失败，json结果转换错误", ResultCodeEnum.SERVICE_ERROR.getCode(), e);
        }
    }

}
